#include "VirtualProgramManager.h"

using namespace OBR;

VirtualProgramManager::VirtualProgramManager()
{
}

VirtualProgramManager::~VirtualProgramManager()
{
}

void VirtualProgramManager::addInstance(std::shared_ptr<VirtualProgramEntry> instance)
{
    // get & create callable id
    const std::type_index &t = typeid(*instance);
    if (this->type2uniqueid.find(t) == this->type2uniqueid.end())
    {
        this->type2uniqueid[t] = this->virtual_program_table.size();
        this->virtual_program_table.push_back(std::vector<std::shared_ptr<VirtualProgramEntry>>());
    }
    // set ids
    instance->program_id = type2uniqueid[t];
    instance->program_instance_id = virtual_program_table[instance->program_id].size();
    // add to storage
    this->virtual_program_table[instance->program_id].push_back(instance);
    this->all_instances.push_back(instance);
}

std::shared_ptr<VirtualProgramEntry> VirtualProgramManager::operator[](uint idx)
{
    return this->all_instances[idx];
}

std::vector<std::shared_ptr<VirtualProgramEntry>> VirtualProgramManager::getUnique()
{
    std::vector<std::shared_ptr<VirtualProgramEntry>> unique;
    for (auto &&type : this->virtual_program_table)
    {
        unique.push_back(type[0]);
    }
    return unique;
}

void VirtualProgramManager::uploadAllPayloads()
{
    for (auto &&instances : this->virtual_program_table)
    {
        instances[0]->uploadVirtualProgramPayload(instances);
    }
}

uint VirtualProgramManager::getUniqueCount()
{
    return this->virtual_program_table.size();
}

int VirtualProgramManager::getInstanceCount()
{
    return this->all_instances.size();
}

int VirtualProgramManager::getInstanceCount(std::type_index typeidx)
{
    if (this->type2uniqueid.find(typeidx) != this->type2uniqueid.end())
    {
        return this->virtual_program_table[this->type2uniqueid[typeidx]].size();
    }
    else
    {
        return 0;
    }
}